﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace RakeSystem
{
    internal class Program
    {
        #region Fields
        private static List<string> _stopList;
        private static List<string> correctKeywords;

        private static readonly List<string> Separators = new List<string>
            {
                " ",
                "\t",
                "\n",
                "\r",
                ".",
                ",",
                "!",
                "?",
                ":",
                ";"
            };

        private static readonly List<Candidate> Candidates = new List<Candidate>();
        private static readonly List<Candidate> KeyCandidates = new List<Candidate>();
        private static readonly List<Word> KeyWords = new List<Word>();
        private static readonly List<Word> Words = new List<Word>();
        private static readonly List<string> StringListOfKeyCandidates = new List<string>();
        private static List<string> _words;
        #endregion

        private static void Main(string[] args)
        {
            _words = ParseCandidates("TestText0.txt");
            ParseStopList("TestStopList0.txt");
            correctKeywords = getCorrectKeywords("TestCorrectKeywords0.txt");
            CreateWords();
            CreateCandidates();
            GetTop();
            print();
            Console.ReadLine();
        }

        private static void ParseStopList(string fileName)
        {
            using (var reader = new StreamReader(fileName))
            {
                _stopList =
                    reader.ReadToEnd()
                          .ToLower()
                          .Split(Separators.ToArray(), StringSplitOptions.RemoveEmptyEntries)
                          .ToList();
            }
        }

        private static List<string> ParseCandidates(string fileName)
        {
            var words = new List<string>();
            using (var reader = new StreamReader(fileName))
            {
                words =
                    reader.ReadToEnd()
                          .ToLower()
                          .Split(Separators.ToArray(), StringSplitOptions.RemoveEmptyEntries)
                          .ToList();
            }
            return words;
        }

        private static void CreateWords()
        {
            foreach (var newWord in _words)
            {
                if (_stopList.Contains(newWord)) continue;
                var flag = true;
                foreach (var word in Words)
                {
                    if (word.Value == newWord)
                    {
                        word.Frequency++;
                        flag = false;
                        break;
                    }
                }
                if (flag)
                {
                    Words.Add(new Word { Deg = 1, Frequency = 1, Value = newWord });
                }
            }
        }

        private static void CreateCandidates()
        {
            var candidate = new Candidate();
            var listWord = new List<Word>();

            foreach (var word in _words)
            {
                if (_stopList.Contains(word))
                {
                    if (listWord.Count != 0)
                    {
                        candidate.Words = listWord;
                        Candidates.Add(candidate);
                        listWord = new List<Word>();
                        candidate = new Candidate();
                    }
                    continue;
                }

                foreach (var savedWord in Words)
                {
                    if (word == savedWord.Value)
                    {
                        listWord.Add(savedWord);
                    }
                }
            }
            candidate.Words = listWord;
            Candidates.Add(candidate);
            CalculateDeg();
        }

        private static void CalculateDeg()
        {
            foreach (var candidate in Candidates)
            {
                var count = candidate.Words.Count - 1;
                foreach (var word in candidate.Words)
                {
                    word.Deg += count;
                }
            }
        }

        private static int calculateTop()
        {
            return Candidates.Count / 3;
        }

        private static void GetTop()
        {
            //int topCount = Candidates.Count/3;
            int topCount = calculateTop();
            var list = Candidates.OrderByDescending(candidate => candidate.Rating).ToList();
            Console.WriteLine("Ключевые слова:");
            var usedWords = new List<string>();
            for (int i = 0; i < topCount; i++)
            {
                var candidate = list[i];
                KeyCandidates.Add(candidate);
                foreach (var word in candidate.Words)
                {
                    Console.Write("{0} ", word.Value);
                    if (!KeyWords.Contains(word)) KeyWords.Add(word);
                }
                Console.WriteLine();
            }
            FillStringListOfKeyCandidates();
        }

        private static void FillStringListOfKeyCandidates()
        {
            foreach (var keyCandidate in KeyCandidates)
            {
                StringListOfKeyCandidates.Add(keyCandidate.Words.Aggregate("", (current, keyWord) => current + keyWord));
            }
        }

        private static List<string> getCorrectKeywords(string fileName)
        {
            var correctKeywords = new List<string>();
            correctKeywords = File.ReadAllLines(fileName).ToList();
            foreach (var keyword in correctKeywords)
            {
                keyword.ToLower();
            }
            /*
            Console.WriteLine("Correct keywords:");
            for (int i = 0; i < correctKeywords.Count; i++)
            {
                Console.WriteLine("{0} ", correctKeywords[i]);
            }*/

            return correctKeywords;
        }

        /*
         * I need here to check if the keyword from KeyCandidates is in the list correctKeywords
         * it's 5 o'clock now and I don't understand how can I do this
         */
        //returns number of correct keywords found by RAKE
        private static int getNumberOfCorrectKeywords()
        {
            var bestWords = new List<string>();
            foreach (var keyWord in KeyWords)
            {
                bestWords.Add(keyWord.Value);
            }
            int number = 0;
            foreach (var keyword in bestWords)
            {
                //Console.WriteLine("keyword from KeyCandidates - {0}", keyword);
                if (correctKeywords.Contains(keyword))
                {
                    number++;
                }
            }
            Console.WriteLine("Number of correct keywords = {0}", number);
            return number;
        }

        private static int calculatePrecision()
        {
            int numCorKeywords = getNumberOfCorrectKeywords();
            int precision = numCorKeywords / calculateTop();
            return precision;
        }

        private static int calculateRecall()
        {
            int numCorKeywordsRAKE = getNumberOfCorrectKeywords();
            int numCorKeywords = correctKeywords.Count;
            int recall = numCorKeywordsRAKE / numCorKeywords;
            return recall;
        }

        private static void print()
        {
            Console.WriteLine("Precision = {0} ", calculatePrecision());
            Console.WriteLine("Recall = {0} ", calculateRecall());
        }
    }
}









//using System;
//using System.Collections.Generic;
//using System.IO;
//using System.Linq;
//
//namespace RakeSystem
//{
//    internal class Program
//    {
//        #region Fields
//        private static List<string> _stopList;
//
//        private static readonly List<string> Separators = new List<string>
//            {
//                " ",
//                "\t",
//                "\n",
//                "\r",
//                ".",
//                ",",
//                "!",
//                "?",
//                ":",
//                ";"
//            };
//
//        private static readonly List<Candidate> Candidates = new List<Candidate>();
//        private static readonly List<Candidate> KeyCandidates = new List<Candidate>();
//        private static readonly List<Word> KeyWords = new List<Word>();
//        private static readonly List<Word> Words = new List<Word>();
//        private static List<string> _words;
//        #endregion
//
//        private static void Main(string[] args)
//        {
//            _words = ParseCandidates("Document.txt");
//            ParseStopList("StopList.txt");
//            CreateWords();
//            CreateCandidates();
//            GetTop();
//            Console.ReadLine();
//        }
//
//        private static void ParseStopList(string fileName)
//        {
//            using (var reader = new StreamReader(fileName))
//            {
//                _stopList =
//                    reader.ReadToEnd()
//                          .ToLower()
//                          .Split(Separators.ToArray(), StringSplitOptions.RemoveEmptyEntries)
//                          .ToList();
//            }
//        }
//
//        private static List<string> ParseCandidates(string fileName)
//        {
//            var words = new List<string>();
//            using (var reader = new StreamReader(fileName))
//            {
//                words =
//                    reader.ReadToEnd()
//                          .ToLower()
//                          .Split(Separators.ToArray(), StringSplitOptions.RemoveEmptyEntries)
//                          .ToList();
//            }
//            return words;
//        }
//
//        private static void CreateWords()
//        {
//            foreach (var newWord in _words)
//            {
//                if (_stopList.Contains(newWord)) continue;
//                var flag = true;
//                foreach (var word in Words)
//                {
//                    if (word.Value == newWord)
//                    {
//                        word.Frequency++;
//                        flag = false;
//                        break;
//                    }
//                }
//                if (flag)
//                {
//                    Words.Add(new Word {Deg = 1, Frequency = 1, Value = newWord});
//                }
//            }
//        }
//
//        private static void CreateCandidates()
//        {
//            var candidate = new Candidate();
//            var listWord = new List<Word>();
//
//            foreach (var word in _words)
//            {
//                if (_stopList.Contains(word))
//                {
//                    if (listWord.Count != 0)
//                    {
//                        candidate.Words = listWord;
//                        Candidates.Add(candidate);
//                        listWord = new List<Word>();
//                        candidate = new Candidate();
//                    }
//                    continue;
//                }
//
//                foreach (var savedWord in Words)
//                {
//                    if (word == savedWord.Value)
//                    {
//                        listWord.Add(savedWord);
//                    }
//                }
//            }
//            candidate.Words = listWord;
//            Candidates.Add(candidate);
//            CalculateDeg();
//        }
//
//        private static void CalculateDeg()
//        {
//            foreach (var candidate in Candidates)
//            {
//                var count = candidate.Words.Count - 1;
//                foreach (var word in candidate.Words)
//                {
//                    word.Deg += count;
//                }
//            }
//        }
//
//        private static void GetTop()
//        {
//            int topCount = Candidates.Count/3;
//            var list = Candidates.OrderByDescending(candidate => candidate.Rating).ToList();
//            Console.WriteLine("Ключевые слова:");
//            var usedWords = new List<string>();
//            for (int i = 0; i < topCount; i++)
//            {
//                var candidate = list[i];
//                KeyCandidates.Add(candidate);
//                foreach (var word in candidate.Words)
//                {
//                    Console.Write("{0} ", word.Value);
//                    if(!KeyWords.Contains(word)) KeyWords.Add(word);
//                }
//                Console.WriteLine();
//            }
//        }
//    }
//}

